<template>
  <el-dialog
    v-model="dialogValue"
    draggable
    :title="title"
    width="700"
    append-to-body
    @open="openDialog"
    @close="handleClose"
  >
    <el-form ref="elFormRef" :model="form" label-width="auto">
      <el-form-item
        label="巷道名称"
        prop="name"
        :rules="{ required: true, message: '请输入巷道名称' }"
      >
        <el-input v-model.trim="form.name" placeholder="请输入" />
      </el-form-item>

      <el-form-item label="巷道数据元" prop="datas" class="coordinates">
        <template v-for="(item, index) in form.coordinates" :key="index">
          <el-row
            :gutter="10"
            :draggable="true"
            align="middle"
            :class="['datas-row', item._dragClass ? item._dragClass : '']"
            @drag="handleDrag(item)"
            @drop="handleDrop(item)"
            @dragleave="handleDragLeave(item)"
            @dragover.prevent="handleDragOver($event, item)"
          >
            <el-col :span="2">
              {{ index + 1 }}
            </el-col>
            <el-col :span="6">
              <el-form-item :prop="`coordinates[${index}].x`" :rules="rule">
                <el-input v-model.number="item.x" placeholder="请输入">
                  <template #prepend>X:</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item :prop="`coordinates[${index}].z`" :rules="rule">
                <el-input v-model.number="item.z" placeholder="请输入">
                  <template #prepend>Y:</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item :prop="`coordinates[${index}].y`" :rules="rule">
                <el-input v-model.number="item.y" placeholder="请输入">
                  <template #prepend>H:</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="3">
              <el-button
                class="delete-btn"
                type="danger"
                plain
                :icon="Delete"
                @click="delDataRow(index)"
              ></el-button>
            </el-col>
          </el-row>
        </template>
        <div class="datas-tools">
          <el-button type="primary" plain :icon="Plus" @click="addDataRow"></el-button>
          <el-button type="primary" plain :icon="CopyDocument" @click="copyDatas"></el-button>
        </div>
      </el-form-item>
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="cancelEditor">取消</el-button>
        <el-button plain type="primary" @click="submit"> 确定 </el-button>
      </div>
    </template>
  </el-dialog>

  <el-dialog v-model="copyDialog" title="CAD命令段" width="500" append-to-body>
    <el-input
      v-model="str"
      placeholder="请输入"
      type="textarea"
      :autosize="{ minRows: 4, maxRows: 8 }"
    ></el-input>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="cancel">取消</el-button>
        <el-button plain type="primary" @click="parse"> 解析 </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import { computed, nextTick, ref, shallowRef, type PropType } from 'vue'
import { ElMessage, FormInstance } from 'element-plus'
import { Plus, Delete, CopyDocument } from '@element-plus/icons-vue'
import { useActiveObject } from '@renderer/stores/activeObject'
import { storeToRefs } from 'pinia'
import emiter from '@renderer/utils/mitt'
import { useHistory } from '@renderer/utils/useHistory'
import { Coordinates, OperationType, Roadway, useAddTools } from '@renderer/utils/useAddTools'
import useEditor from '@renderer/utils/useEditor'
import { saveModel } from '@renderer/api'
import { useViewportStore } from '@renderer/stores/viewport'
const title = ref('添加巷道')

const props = defineProps({
  modelValue: {
    type: Boolean
  },
  check: {
    type: Boolean,
    default: false
  },
  type: {
    type: String as PropType<OperationType>,
    default: 'add'
  }
})

const emit = defineEmits({
  'update:modelValue': (val: boolean) => val
})

const activeObjectStore = useActiveObject()
const { activeShallowRef, activeVO } = storeToRefs(activeObjectStore)
const oCurrentObj = shallowRef()
function openDialog() {
  if (props.type === 'edit') {
    oCurrentObj.value = activeVO.value?.clone()
    oCurrentObj.value.uuid = activeVO.value.uuid
    if (!activeShallowRef.value._isEditor) {
      createdRoadwayEdit(activeVO.value.geometry.parameters.path.points)
    }
    const obj = activeShallowRef.value
    title.value = '修改 - ' + obj.name
    form.value = {
      name: obj.name,
      tunnelId: obj.uuid,
      coordinates: JSON.parse(JSON.stringify(obj.geometry.parameters.path.points))
    }
  }
}

const dialogValue = computed({
  get() {
    return props.modelValue
  },
  set(val) {
    emit('update:modelValue', val)
  }
})

const form = ref<Roadway>({
  name: '',
  coordinates: [],
  closed: false
})
const rule = [
  { required: true, message: '请输入坐标' },
  { type: 'number', message: '请输入数字' }
]

const elFormRef = ref<FormInstance>()
const { addRoadway, hasGroup } = useAddTools()
const { commitHistory } = useHistory()
const { createdRoadwayEdit, closeEditor } = useEditor()
const viewportStore = useViewportStore()
const { publicGroup } = storeToRefs(viewportStore)
function submit(close: boolean = true) {
  elFormRef.value?.validate((valid) => {
    if (valid) {
      if (activeShallowRef.value?._isEditor) {
        closeEditor()
      }
      addRoadway(props.type, form.value, form.value.closed)
      nextTick(async () => {
        createdRoadwayEdit(activeVO.value?.geometry.parameters.path.points)
        emiter.emit('viewChange')
        commitHistory(title.value, 'import')
        const data = publicGroup.value?.toJSON()
        data.object.children = data.object.children?.filter((obj) => obj.name !== 'editor')
        await saveModel(data)
        if (close) {
          dialogValue.value = false
        }
      })
    }
  })
}
function cancelEditor() {
  closeEditor()
  const Object3D = activeShallowRef.value
  activeObjectStore.setActiveVO(undefined)
  Object3D?.parent?.remove(Object3D)
  const group = hasGroup('巷道')
  group.add(oCurrentObj.value)
  activeObjectStore.setActiveVO(oCurrentObj.value)
  createdRoadwayEdit(oCurrentObj.value.geometry.parameters.path.points)
  emiter.emit('viewChange')
  commitHistory(title.value, 'import')
  dialogValue.value = false
}
function handleClose() {
  elFormRef.value?.resetFields()
  form.value.coordinates = []
}

function addDataRow() {
  form.value.coordinates.push({
    x: undefined,
    y: undefined,
    z: undefined
  })
}

function delDataRow(index: number) {
  form.value.coordinates.splice(index, 1)
  submit(false)
}
function copyDatas() {
  copyDialog.value = true
}
// 粘贴CAD命令段
const copyDialog = ref(false)
const str = ref('')
// 解析命令段
function parse() {
  if (str.value) {
    let match
    const regex = /X=([\d.]+)\s+Y=([\d.]+)\s+Z=\s*([\d.]+)/g
    while ((match = regex.exec(str.value)) !== null) {
      // 将每个匹配的坐标值 (X, Y, Z) 作为数组项存入数组
      form.value.coordinates.push({
        x: parseFloat(match[2]),
        y: parseFloat(match[3]),
        z: parseFloat(match[1])
      })
    }
    cancel()
  } else {
    ElMessage({
      message: '请输入',
      type: 'warning'
    })
  }
}
function cancel() {
  str.value = ''
  copyDialog.value = false
}

// 拖拽
const currentDrag = ref()
function handleDrag(item) {
  currentDrag.value = item
}
// 拖拽中
function handleDragOver(
  e: { offsetY: number; target: { clientHeight: number } },
  data: Coordinates
) {
  const area = e.offsetY / e.target.clientHeight
  if (area < 0.25) {
    data._dragClass = 'dragTop'
  } else if (area > 0.75) {
    data._dragClass = 'dragBottom'
  }
}
function handleDragLeave(data: Coordinates) {
  data._dragClass = ''
}
// 拖拽结束放下
function handleDrop(data: Coordinates) {
  if (!currentDrag.value || data.x === currentDrag.value.x) return

  const oldIndex = form.value.coordinates.findIndex((item) => {
    return (
      item.x === currentDrag.value.x &&
      item.y === currentDrag.value.y &&
      item.z === currentDrag.value.z
    )
  })
  form.value.coordinates.splice(oldIndex, 1)

  let nextIndex = form.value.coordinates.findIndex((item) => {
    return item.x === data.x && item.y === data.y && item.z === data.z
  })
  if (data._dragClass === 'dragBottom') {
    nextIndex = nextIndex + 1
  }
  form.value.coordinates.splice(nextIndex, 0, currentDrag.value)
  data._dragClass = ''
  submit(false)
}
</script>
<style lang="scss" scoped>
.datas-row {
  user-select: none;
  padding-bottom: 10px;

  ::v-deep(.el-input-group__prepend) {
    padding: 0 10px;
  }

  &.dragTop {
    border-top: 1px dashed var(--active-color);
  }

  &.dragBottom {
    border-bottom: 1px dashed var(--active-color);
  }
}
.coordinates {
  max-height: 60vh;
  overflow: auto;
}
.datas-tools {
  margin: 0 auto;

  & > .el-button {
    width: 80px;
  }
}
</style>
